<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能棋类计时器</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        /* 保持原有样式不变 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            touch-action: manipulation;
        }

        body {
            font-family: Arial, sans-serif;
            height: 100vh;
            display: flex;
            flex-direction: column;
            background: #f5f5f5;
        }

        .settings-panel {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            z-index: 100;
            width: 320px;
            display: none;
        }
        .settings-panel.active {
            display: block;
        }
        .settings-group {
            margin-bottom: 15px;
        }
        .settings-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
            color: #333;
        }
        .time-inputs {
            display: flex;
            gap: 10px;
        }
        .time-input {
            flex: 1;
        }
        .time-input input {
            width: 100%;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
        }
        .mode-select {
            display: grid;
            gap: 8px;
        }
        .mode-option {
            padding: 10px;
            border: 2px solid #eee;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s;
        }
        .mode-option.selected {
            border-color: #2196F3;
            background: #e3f2fd;
        }

        .timer-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            position: relative;
        }

        .player {
            flex: 1;
            display: flex;
            background-color: #fff;
            position: relative;
        }

        #player2 {
            transform: rotate(180deg);
        }

        .player-content {
            flex: 1;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            transform: rotate(-180deg);
            padding: 30px 0;
        }

        .main-time {
            font-size: 20vw;
            line-height: 1;
            display: flex;
            gap: 0.2em;
        }

        .step-time {
            font-size: 5vw;
            color: #666;
            display: flex;
            gap: 0.2em;
            margin-bottom: 15px;
        }

        #player2 .player-content {
            flex-direction: column-reverse;
        }
        #player2 .step-time {
            margin-bottom: 0;
            margin-top: 15px;
        }

        .time-number {
            min-width: 1.2em;
            text-align: center;
        }

        .player.active {
            background-color: #4CAF50;
        }
        .player.active .main-time,
        .player.active .step-time {
            color: white;
        }

        .control-area {
            position: fixed;
            right: 20px;
            top: 50%;
            transform: translateY(-50%);
            z-index: 10;
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        .controls {
            display: flex;
            flex-direction: column;
            gap: 15px;
            background: white;
            padding: 15px 10px;
            border-radius: 15px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.15);
        }

        button {
            width: 50px;
            height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 20px;
            border: none;
            border-radius: 50%;
            background-color: #2196F3;
            color: white;
            cursor: pointer;
            transition: all 0.2s;
        }
        
        button:active {
            transform: scale(0.95);
            background-color: #1976D2;
        }
        
        #settingsBtn {
            background-color: #666;
        }
        
        #resetBtn {
            background-color: #FF5722;
        }
        
        #soundBtn {
            background-color: #4CAF50;
        }
        
        .mode-display-container {
            position: absolute;
            width: 100%;
            z-index: 5;
            display: flex;
            justify-content: center;
            pointer-events: none;
        }
        
        .mode-display {
            background: white;
            padding: 8px 15px;
            border-radius: 20px;
            margin: 15px 0;
            font-weight: bold;
            color: #333;
            box-shadow: 0 2px 6px rgba(0,0,0,0.1);
            pointer-events: auto;
        }
        
        .mode-display.player1 {
            transform: rotate(180deg);
        }

        .timeout-alert {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
            text-align: center;
            z-index: 1000;
            min-width: 300px;
        }
        .timeout-alert h3 {
            font-size: 24px;
            margin-bottom: 15px;
            color: #e53935;
        }
        .timeout-alert p {
            font-size: 18px;
            margin-bottom: 20px;
            color: #333;
        }
        .timeout-alert button {
            padding: 12px 25px;
            font-size: 16px;
            background-color: #4CAF50;
            transition: background-color 0.3s;
        }
        .timeout-alert button:hover {
            background-color: #388E3C;
        }
        .timeout-alert.player1 {
            transform: translate(-50%, -50%) rotate(180deg);
        }

        .player-name {
            position: absolute;
            left: 20px;
            top: 20px;
            font-size: 42px;
            font-weight: bold;
            color: #333;
            z-index: 5;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
            transition: color 0.3s, text-shadow 0.3s;
        }
        
        #player1 .player-name {
            transform: rotate(-180deg);
        }
        
        #player2 .player-name {
            transform: rotate(180deg);
        }
        
        .player.active .player-name {
            color: white;
            text-shadow: 0 0 8px rgba(255,255,255,0.5);
        }

        .error-alert {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
            text-align: center;
            z-index: 1000;
            min-width: 300px;
        }
        .error-alert h3 {
            color: #e53935;
            margin-bottom: 15px;
        }
    </style>
</head>
<body>
    <!-- 修复的设置面板结构 -->
    <div class="settings-panel" id="settingsPanel">
        <div class="settings-group">
            <label>计时模式：</label>
            <div class="mode-select">
                <div class="mode-option" data-mode="countdown" onclick="selectMode('countdown')">
                    读秒制（超时后读秒）
                </div>
                <div class="mode-option" data-mode="increment" onclick="selectMode('increment')">
                    加秒制（每步加时）
                </div>
                <div class="mode-option" data-mode="step" onclick="selectMode('step')">
                    步时制（独立步时）
                </div>
            </div>
        </div>

        <div class="settings-group">
            <label>局时设置（总时间）：</label>
            <div class="time-inputs">
                <div class="time-input">
                    <input type="number" id="mainMinutes" min="0" max="99" value="10" placeholder="分">
                </div>
                <div class="time-input">
                    <input type="number" id="mainSeconds" min="0" max="99" value="0" placeholder="秒">
                </div>
            </div>
        </div>

        <div class="settings-group">
            <label>读秒设置：</label>
            <div class="time-inputs">
                <div class="time-input">
                    <input type="number" id="stepMinutes" min="0" max="99" value="0" placeholder="分">
                </div>
                <div class="time-input">
                    <input type="number" id="stepSeconds" min="0" max="99" value="30" placeholder="秒">
                </div>
            </div>
        </div>

        <div class="settings-group">
            <label>玩家姓名设置：</label>
            <div class="time-inputs">
                <div class="time-input">
                    <input type="text" id="player1Name" placeholder="玩家1姓名" value="玩家1">
                </div>
                <div class="time-input">
                    <input type="text" id="player2Name" placeholder="玩家2姓名" value="玩家2">
                </div>
            </div>
        </div>

        <button onclick="applySettings()" style="width:100%;margin-top:15px;border-radius:10px;height:auto;">应用设置</button>
    </div>

    <!-- 主计时界面 -->
    <div class="timer-container">
        <!-- 玩家1的模式显示 -->
        <div class="mode-display-container" style="top: 0;">
            <div class="mode-display player1" id="modeDisplay1">读秒制</div>
        </div>
        
        <div id="player1" class="player">
            <div class="player-name" id="player1NameDisplay">玩家1</div>
            <div class="player-content">
                <div class="step-time">
                    <span class="step-min">00</span><span>:</span><span class="step-sec">00</span>
                </div>
                <div class="main-time">
                    <span class="main-min">10</span><span>:</span><span class="main-sec">00</span>
                </div>
            </div>
        </div>

        <div class="control-area">
            <div class="controls">
                <button id="settingsBtn" onclick="toggleSettings()"><i class="fas fa-cog"></i></button>
                <button id="resetBtn" onclick="resetTimers()"><i class="fas fa-redo-alt"></i></button>
                <button id="soundBtn" onclick="toggleSound()"><i id="soundIcon" class="fas fa-volume-up"></i></button>
            </div>
        </div>

        <!-- 玩家2的模式显示 -->
        <div class="mode-display-container" style="bottom: 0;">
            <div class="mode-display" id="modeDisplay2">读秒制</div>
        </div>

        <div id="player2" class="player">
            <div class="player-name" id="player2NameDisplay">玩家2</div>
            <div class="player-content">
                <div class="main-time">
                    <span class="main-min">10</span><span>:</span><span class="main-sec">00</span>
                </div>
                <div class="step-time">
                    <span class="step-min">00</span><span>:</span><span class="step-sec">00</span>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 配置对象
        let config = {
            mode: 'countdown',      
            mainTime: 600,     
            stepTime: 30,      
            time1: 600,       
            time2: 600,       
            activePlayer: null,
            timer: null,
            soundEnabled: true,
            playerNames: {
                1: "玩家1",
                2: "玩家2"
            },
            overtimeStatus: {
                1: { inOvertime: false, stepRemaining: 0 },
                2: { inOvertime: false, stepRemaining: 0 }
            }
        };

        // 音频上下文
        let audioContext;
        try {
            audioContext = new (window.AudioContext || window.webkitAudioContext)();
        } catch(e) {
            console.log('浏览器不支持Web Audio API');
        }

        // 初始化设置
        function initSettings() {
            // 确保元素存在
            const mainMinutesElem = document.getElementById('mainMinutes');
            const mainSecondsElem = document.getElementById('mainSeconds');
            const stepMinutesElem = document.getElementById('stepMinutes');
            const stepSecondsElem = document.getElementById('stepSeconds');
            const player1NameElem = document.getElementById('player1Name');
            const player2NameElem = document.getElementById('player2Name');

            if (!mainMinutesElem || !mainSecondsElem || !stepMinutesElem || !stepSecondsElem || !player1NameElem || !player2NameElem) {
                console.error('找不到输入元素');
                return;
            }

            // 模式选择
            document.querySelectorAll('.mode-option').forEach(opt => {
                opt.classList.remove('selected');
                if(opt.dataset.mode === config.mode) {
                    opt.classList.add('selected');
                }
            });
            
            // 主时间设置
            const mainMins = Math.floor(config.mainTime / 60);
            const mainSecs = config.mainTime % 60;
            mainMinutesElem.value = mainMins;
            mainSecondsElem.value = mainSecs;
            
            // 读秒时间设置
            const stepMins = Math.floor(config.stepTime / 60);
            const stepSecs = config.stepTime % 60;
            stepMinutesElem.value = stepMins;
            stepSecondsElem.value = stepSecs;
            
            // 玩家姓名设置
            player1NameElem.value = config.playerNames[1];
            player2NameElem.value = config.playerNames[2];
            
            updateDisplay();
            updatePlayerNames();
        }

        // 新增输入验证函数
        function sanitizeInput(input, type = 'number', maxLength = 20) {
            if (type === 'number') {
                // 只允许数字，并限制最大值
                return Math.min(Number(input.replace(/\D/g, '')), 99);
            } else if (type === 'text') {
                // 去除HTML标签，限制长度
                return input.replace(/<[^>]*>?/gm, '').substring(0, maxLength);
            }
            return input;
        }

        // 修改applySettings函数
        function applySettings() {
            try {
                const mainMinutes = sanitizeInput(document.getElementById('mainMinutes').value);
                const mainSeconds = sanitizeInput(document.getElementById('mainSeconds').value);
                const stepMinutes = sanitizeInput(document.getElementById('stepMinutes').value);
                const stepSeconds = sanitizeInput(document.getElementById('stepSeconds').value);
                const player1Name = sanitizeInput(document.getElementById('player1Name').value.trim(), 'text');
                const player2Name = sanitizeInput(document.getElementById('player2Name').value.trim(), 'text');
                
                // 验证输入是否有效
                if (isNaN(mainMinutes) || isNaN(mainSeconds) || isNaN(stepMinutes) || isNaN(stepSeconds)) {
                    throw new Error('请输入有效的数字');
                }

                config.mainTime = mainMinutes * 60 + mainSeconds;
                config.stepTime = stepMinutes * 60 + stepSeconds;
                config.playerNames[1] = player1Name || "玩家1";
                config.playerNames[2] = player2Name || "玩家2";
                
                updateModeDisplay();
                updatePlayerNames();
                resetTimers();
                toggleSettings();
            } catch (error) {
                showError(error.message);
            }
        }

        function selectMode(mode) {
            config.mode = mode;
            document.querySelectorAll('.mode-option').forEach(opt => {
                opt.classList.toggle('selected', opt.dataset.mode === mode);
            });
            updateModeDisplay();
            resetTimers();
        }

        function toggleSettings() {
            const panel = document.getElementById('settingsPanel');
            panel.classList.toggle('active');
            if(panel.classList.contains('active')) {
                initSettings();
            }
        }

        function formatTime(seconds) {
            const mins = Math.floor(seconds / 60).toString().padStart(2, '0');
            const secs = (seconds % 60).toString().padStart(2, '0');
            return { mins, secs };
        }

        function updateDisplay() {
            // 主计时更新
            const main1 = formatTime(config.time1);
            const main2 = formatTime(config.time2);
            document.querySelectorAll('#player1 .main-min, #player1 .main-sec').forEach((el, i) => {
                el.textContent = i === 0 ? main1.mins : main1.secs;
            });
            document.querySelectorAll('#player2 .main-min, #player2 .main-sec').forEach((el, i) => {
                el.textContent = i === 0 ? main2.mins : main2.secs;
            });

            // 步时显示逻辑
            [1, 2].forEach(player => {
                let displayTime;
                
                if (config.mode === 'countdown') {
                    // 读秒制：显示读秒时间或默认步时
                    displayTime = config.overtimeStatus[player].inOvertime ? 
                        formatTime(config.overtimeStatus[player].stepRemaining) : 
                        formatTime(config.stepTime);
                } else if (config.mode === 'increment') {
                    // 加秒制：显示将要增加的时间
                    displayTime = formatTime(config.stepTime);
                } else if (config.mode === 'step') {
                    // 步时制：显示剩余步时
                    displayTime = formatTime(config.overtimeStatus[player].stepRemaining || config.stepTime);
                }
                
                document.querySelectorAll(`#player${player} .step-min, #player${player} .step-sec`)
                    .forEach((el, i) => {
                        el.textContent = i === 0 ? displayTime.mins : displayTime.secs;
                    });
            });
        }

        function playBeep() {
            if (!config.soundEnabled || !audioContext) return;
            const oscillator = audioContext.createOscillator();
            const gainNode = audioContext.createGain();
            oscillator.connect(gainNode);
            gainNode.connect(audioContext.destination);
            oscillator.frequency.value = 800;
            gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
            oscillator.start();
            oscillator.stop(audioContext.currentTime + 0.1);
        }

        function startOvertime(player) {
            const playerNum = player === 'player1' ? 1 : 2;
            config.overtimeStatus[playerNum].inOvertime = true;
            config.overtimeStatus[playerNum].stepRemaining = config.stepTime;
            
            clearInterval(config.timer);
            config.timer = setInterval(() => {
                config.overtimeStatus[playerNum].stepRemaining--;
                
                if(config.overtimeStatus[playerNum].stepRemaining < 0) {
                    clearInterval(config.timer);
                    showTimeout(playerNum, true);
                }
                updateDisplay();
            }, 1000);
        }

        function showTimeout(playerNum, isStepTimeout = false) {
            const alertDiv = document.createElement('div');
            alertDiv.className = 'timeout-alert';
            // 如果是玩家1，添加player1类以旋转显示
            if (playerNum === 1) {
                alertDiv.classList.add('player1');
            }
            
            alertDiv.innerHTML = `
                <h3>${config.playerNames[playerNum]} 已超时！</h3>
                <p>${isStepTimeout ? '步时耗尽' : '主时间耗尽'}，判负！</p>
                <button onclick="this.parentElement.remove();resetTimers()">确定</button>
            `;
            document.body.appendChild(alertDiv);
            stopAllTimers();
        }

        function stopAllTimers() {
            clearInterval(config.timer);
            config.activePlayer = null;
            document.querySelectorAll('.player').forEach(p => p.classList.remove('active'));
        }

        function handlePlayerClick(event) {
            const clickedPlayer = event.currentTarget.id;
            
            // 初始点击开始游戏
            if (!config.activePlayer) {
                startTimer(clickedPlayer === 'player1' ? 'player2' : 'player1');
                startTimer(clickedPlayer);
                return;
            }

            const currentPlayer = config.activePlayer;
            if (clickedPlayer !== currentPlayer) return;

            playBeep();
            
            // 根据不同模式处理计时逻辑
            const playerNum = currentPlayer === 'player1' ? 1 : 2;
            const otherPlayerNum = playerNum === 1 ? 2 : 1;
            const otherPlayer = playerNum === 1 ? 'player2' : 'player1';
            
            if(config.mode === 'countdown') {
                // 读秒模式特殊处理
                config.overtimeStatus[otherPlayerNum].inOvertime = false;
                config.overtimeStatus[otherPlayerNum].stepRemaining = 0;
            } 
            else if(config.mode === 'increment') {
                // 加秒制：每步结束后增加时间
                config[`time${playerNum}`] += config.stepTime;
            }
            else if(config.mode === 'step') {
                // 步时制：重置当前玩家的步时，并开始下一位玩家的步时
                config.overtimeStatus[playerNum].stepRemaining = 0; // 当前玩家步时清零
                config.overtimeStatus[otherPlayerNum].stepRemaining = config.stepTime; // 下一位玩家步时重置
            }

            const switchTo = currentPlayer === 'player1' ? 'player2' : 'player1';
            startTimer(switchTo);
        }

        // 优化定时器更新
        let lastUpdate = 0;
        const UPDATE_INTERVAL = 200; // 每200ms更新一次显示

        function startTimer(targetPlayer) {
            clearInterval(config.timer);
            document.querySelectorAll('.player').forEach(p => p.classList.remove('active'));
            
            config.activePlayer = targetPlayer;
            document.getElementById(targetPlayer).classList.add('active');
            
            const playerNum = targetPlayer === 'player1' ? 1 : 2;
            const now = Date.now();
            
            if(!config.overtimeStatus[playerNum].inOvertime) {
                config.timer = setInterval(() => {
                    const currentTime = Date.now();
                    if (currentTime - lastUpdate >= UPDATE_INTERVAL) {
                        lastUpdate = currentTime;
                        updateDisplay();
                    }
                    
                    // 主时间始终减少
                    config[`time${playerNum}`]--;
                    
                    // 步时制模式下，同时减少步时
                    if (config.mode === 'step') {
                        config.overtimeStatus[playerNum].stepRemaining--;
                        
                        // 步时耗尽判负
                        if (config.overtimeStatus[playerNum].stepRemaining < 0) {
                            clearInterval(config.timer);
                            showTimeout(playerNum, true);
                            return;
                        }
                    }
                    
                    // 主时间耗尽的处理
                    if(config[`time${playerNum}`] < 0) {
                        config[`time${playerNum}`] = 0;
                        // 只有读秒制才会进入读秒状态
                        if (config.mode === 'countdown') {
                            startOvertime(targetPlayer);
                        } else {
                            clearInterval(config.timer);
                            showTimeout(playerNum);
                        }
                    }
                }, 1000);
            }
            else {
                startOvertime(targetPlayer);
            }
        }

        function resetTimers() {
            clearInterval(config.timer);
            config.time1 = config.mainTime;
            config.time2 = config.mainTime;
            config.activePlayer = null;
            config.overtimeStatus = {
                1: { inOvertime: false, stepRemaining: config.mode === 'step' ? config.stepTime : 0 },
                2: { inOvertime: false, stepRemaining: config.mode === 'step' ? config.stepTime : 0 }
            };
            document.querySelectorAll('.player').forEach(p => p.classList.remove('active'));
            document.querySelectorAll('.timeout-alert').forEach(a => a.remove());
            updateDisplay();
            playBeep();
        }

        function toggleSound() {
            config.soundEnabled = !config.soundEnabled;
            const soundIcon = document.getElementById('soundIcon');
            if (config.soundEnabled) {
                soundIcon.className = 'fas fa-volume-up';
            } else {
                soundIcon.className = 'fas fa-volume-mute';
            }
        }

        function updateModeDisplay() {
            const modeText = {
                'countdown': '读秒制',
                'increment': '加秒制',
                'step': '步时制'
            };
            const currentMode = modeText[config.mode] || '读秒制';
            document.getElementById('modeDisplay1').textContent = currentMode;
            document.getElementById('modeDisplay2').textContent = currentMode;
        }

        function updatePlayerNames() {
            document.getElementById('player1NameDisplay').textContent = config.playerNames[1];
            document.getElementById('player2NameDisplay').textContent = config.playerNames[2];
        }

        // 新增错误提示函数
        function showError(message) {
            const errorDiv = document.createElement('div');
            errorDiv.className = 'error-alert';
            errorDiv.innerHTML = `
                <h3>错误</h3>
                <p>${message}</p>
                <button onclick="this.parentElement.remove()">确定</button>
            `;
            document.body.appendChild(errorDiv);
        }

        // 事件监听
        document.getElementById('player1').addEventListener('click', handlePlayerClick);
        document.getElementById('player2').addEventListener('click', handlePlayerClick);
        
        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            initSettings();
            updateDisplay();
            updateModeDisplay();
            updatePlayerNames();
            
            // 初始化步时制的步时
            if (config.mode === 'step') {
                config.overtimeStatus[1].stepRemaining = config.stepTime;
                config.overtimeStatus[2].stepRemaining = config.stepTime;
            }
        });

        // 将代码模块化
        const Timer = (() => {
            let config = {
                // 原有配置
            };

            const init = () => {
                // 初始化代码
            };

            const startTimer = (targetPlayer) => {
                // 定时器代码
            };

            const resetTimers = () => {
                // 重置代码
            };

            return {
                init,
                startTimer,
                resetTimers
            };
        })();

        // 事件监听
        document.addEventListener('DOMContentLoaded', () => {
            Timer.init();
        });

        // 增加注释
        /**
         * 格式化时间显示
         * @param {number} seconds - 总秒数
         * @returns {Object} 包含分钟和秒数的对象
         */
        function formatTime(seconds) {
            const mins = Math.floor(seconds / 60).toString().padStart(2, '0');
            const secs = (seconds % 60).toString().padStart(2, '0');
            return { mins, secs };
        }
    </script>
</body>
</html>